import React from 'react';
import LogFactory from "log/LogFactory";
import {FormInstance} from "antd/lib";
import {App} from "antd";
import {AsyncThunkAction} from "@reduxjs/toolkit";
import {AsyncThunkConfig} from "@reduxjs/toolkit/src/createAsyncThunk";
import {Part} from "type/Part";
import {
    AsyncThunkFulfilledActionCreator,
    AsyncThunkPendingActionCreator,
    AsyncThunkRejectedActionCreator
} from "@reduxjs/toolkit/dist/createAsyncThunk";
import {compareObjectToDifference} from "util/compare";
import {useNavigate} from "react-router-dom";
import Entity from "type/Entity";

import {useAppDispatch} from "../redux/hook";
import {Result} from "../type/Result";
import useAsyncEffect from "./useAsyncEffect";

const log = LogFactory.getLog("UseInitData");
/**
 * 通过url获取初始化数据
 * @param dataFunc Promise数据
 * @param form 表单实例
 * @param asyncAction 更新数据异步action
 * @param dataConvert 数据转换函数,当用户提交表单时,将表单数据转换为提交数据,默认为表单数据
 * @param formConvert 表单转换函数,当初始化数据后,将数据转换为表单数据,默认为初始化数据
 * @return {loading} 加载状态(包含初始化和提交数据)
 * @return {callback} 回调函数,用于表单提交,参数为表单数据
 * @template T 数据类型
 */
const useFormUpdate = <T extends Entity> (dataFunc: Promise<Result<T>>, form: FormInstance<T>, asyncAction: ((arg: T) => AsyncThunkAction<T | null, Part, AsyncThunkConfig>) & {
    pending: AsyncThunkPendingActionCreator<T, AsyncThunkConfig>;
    rejected: AsyncThunkRejectedActionCreator<T, AsyncThunkConfig>;
    fulfilled: AsyncThunkFulfilledActionCreator<T | null, T, AsyncThunkConfig>;
    settled: (action: any) => action is ReturnType<AsyncThunkRejectedActionCreator<T, AsyncThunkConfig> | AsyncThunkFulfilledActionCreator<Part | null, T, AsyncThunkConfig>>;
    typePrefix: string
},dataConvert?: (data: Partial<T>) => Partial<T>,formConvert?: (data: Partial<T>) => Partial<T>): [boolean, (value: T) => Promise<void>] => {

    const [loading, setLoading] = React.useState<boolean>(true);
    const [data, setData] = React.useState<T>();
    const {message} = App.useApp() ;
    const dispatch = useAppDispatch() ;
    const navigate = useNavigate() ;

    useAsyncEffect(async () => {
        const res = await dataFunc ;
        if (!res.success){
            log.warn("数据为空",res) ;
            return ;
        }
        setData(res.data) ;
        setTimeout(() => {
            if (formConvert) {
                form.setFieldsValue(formConvert(res.data) as object);
            }else {
                form.setFieldsValue(res.data as object);
            }
        },100) ;
        setLoading(false) ;
    });
    const callback = async (value: T) => {
        log.debug("表单提交数据:",value) ;
        if (data === void 0){
            log.error("未找到数据") ;
            return ;
        }
        let compRes = compareObjectToDifference(data,value) ;
        if (compRes === null){
            log.debug("没有差异,不需要更新") ;
            message.info("数据没有变化") ;
            return ;
        }
        setLoading(true) ;
        log.debug("需要更新的数据: ",compRes) ;
        if (dataConvert){
          compRes = dataConvert(compRes) ;
        }
        compRes.id = data.id ;
        const res = await dispatch(asyncAction(compRes as T)).unwrap() ;
        if (res === null){
            message.error("更新失败") ;
        }else {
            message.success("更新成功") ;
            navigate(-1) ;
        }
        setLoading(false) ;
    } ;
    return [loading,callback];
};

export default useFormUpdate;